package cn.qianxun.meta.dict.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.qianxun.meta.common.core.dto.RowsData;
import cn.qianxun.meta.common.core.web.vo.RemoveLongDTO;
import cn.qianxun.meta.dict.dto.AddDictTypeDTO;
import cn.qianxun.meta.dict.dto.QueryDictTypeDTO;
import cn.qianxun.meta.dict.entity.SysDictData;
import cn.qianxun.meta.dict.entity.SysDictType;
import cn.qianxun.meta.dict.mapper.SysDictDataMapper;
import cn.qianxun.meta.dict.mapper.SysDictTypeMapper;
import cn.qianxun.meta.dict.service.ISysDictTypeService;
import cn.qianxun.meta.dict.util.DictUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import cn.qianxun.meta.common.core.constant.Constants;
import cn.qianxun.meta.common.core.constant.UserConstants;
import cn.qianxun.meta.common.core.exception.ServiceException;
import cn.qianxun.meta.common.core.manager.AsyncManager;
import cn.qianxun.meta.common.satoken.utils.LoginHelper;
import cn.qianxun.meta.dict.vo.SysDictTypeVO;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.TimerTask;

/**
 * <p>
 * 字典类型表 服务实现类
 * </p>
 *
 * @author fuzhilin
 * @since 2023/08/24
 */
@Service
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class SysDictTypeServiceImpl extends ServiceImpl<SysDictTypeMapper, SysDictType> implements ISysDictTypeService {
    private final SysDictTypeMapper sysDictTypeMapper;
    private final SysDictDataMapper sysDictDataMapper;

    @Override
    public RowsData<SysDictTypeVO> selectDictTypeList(QueryDictTypeDTO dto) {
        Page<Object> page = PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        List<SysDictTypeVO> list = sysDictTypeMapper.selectDictTypeList(dto);
        return new RowsData<SysDictTypeVO>(list, page.getTotal(), dto.getPageNum());
    }

    @Override
    public SysDictTypeVO details(Long dictId) {
        SysDictTypeVO typeDTO = new SysDictTypeVO();
        SysDictType dictType = sysDictTypeMapper.selectById(dictId);
        BeanUtils.copyProperties(dictType, typeDTO);
        return typeDTO;
    }

    @Override
    public SysDictTypeVO details(String dictType) {
        SysDictTypeVO typeDTO = new SysDictTypeVO();
        SysDictType sysDictType = sysDictTypeMapper.selectOne(new LambdaQueryWrapper<SysDictType>()
                .eq(SysDictType::getDictType, dictType));
        BeanUtils.copyProperties(sysDictType, typeDTO);
        return typeDTO;
    }

    @Override
    public void addDictType(AddDictTypeDTO dto) {
        SysDictType dictType = new SysDictType();
        BeanUtils.copyProperties(dto, dictType);
        Long count = sysDictTypeMapper.selectCount(new LambdaQueryWrapper<SysDictType>().eq(SysDictType::getDictName, dictType.getDictName()));
        if (count > 0) {
            throw new ServiceException("该类型名称已存在，请换一个试试！");
        }
        if (UserConstants.NOT_UNIQUE.equals(checkDictTypeUnique(dictType))) {
            throw new ServiceException("新增字典'" + dictType.getDictName() + "'失败，字典类型已存在");
        }
        dictType.setCreateBy(LoginHelper.getUserName());
        dictType.setCreateTime(new Date());
        sysDictTypeMapper.insert(dictType);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void editDictType(AddDictTypeDTO dto) {
        SysDictType dictType = sysDictTypeMapper.selectById(dto.getDictId());
        String oldDictType = dictType.getDictType();
        BeanUtils.copyProperties(dto, dictType);
        if (UserConstants.NOT_UNIQUE.equals(checkDictTypeUnique(dictType))) {
            throw new ServiceException("修改字典'" + dictType.getDictName() + "'失败，字典类型已存在");
        }
        dictType.setUpdateBy(LoginHelper.getUserName());
        dictType.setUpdateTime(new Date());
        sysDictTypeMapper.updateById(dictType);
        SysDictData dictData = new SysDictData();
        dictData.setDictType(dictType.getDictType());
        sysDictDataMapper.update(dictData,
                new LambdaQueryWrapper<SysDictData>()
                        .eq(SysDictData::getDictType, oldDictType));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteDictTypeByIds(RemoveLongDTO vo) {
        for (Long dictId : vo.getRemoveIdList()) {
            SysDictType dictType = sysDictTypeMapper.selectById(dictId);
            if (sysDictTypeMapper.countDictDataByType(dictType.getDictType()) > 0) {
                throw new ServiceException(String.format("%1$s已分配,不能删除", dictType.getDictName()));
            }
            if (dictType.getStatus().equals(Constants.STATUS_NORMAL)) {
                throw new ServiceException(String.format("%1$s正在使用,不可删除", dictType.getDictName()));
            }
            sysDictDataMapper.delete(new LambdaQueryWrapper<SysDictData>().eq(SysDictData::getDictType, dictType.getDictType()));
        }
        int count = sysDictTypeMapper.deleteDictTypeByIds(vo.getRemoveIdList());
        if (count > 0) {
            DictUtils.clearDictCache();
            initdictdata();
        }
    }

    @Override
    public void clearCache() {
        DictUtils.clearDictCache();
        initdictdata();
    }

    /**
     * 校验字典类型称是否唯一
     *
     * @param dict 字典类型
     * @return 结果
     */
    public String checkDictTypeUnique(SysDictType dict) {
        Long dictId = StrUtil.isEmpty(String.valueOf(dict.getDictId())) ? null : dict.getDictId();
        SysDictType dictType = sysDictTypeMapper.selectOne(new LambdaQueryWrapper<SysDictType>()
                .eq(SysDictType::getDictType, dict.getDictType())
                .last("limit 1"));
        if (ObjectUtil.isNotNull(dictType) && !dictType.getDictId().equals(dictId)) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    public void initdictdata() {
        AsyncManager.me().execute(new TimerTask() {
            @Override
            public void run() {
                List<SysDictType> dictTypeList = sysDictTypeMapper.selectList(new QueryWrapper<>());
                for (SysDictType dictType : dictTypeList) {
                    List<SysDictData> dictDatas = sysDictDataMapper.selectList(new LambdaQueryWrapper<SysDictData>().eq(SysDictData::getDictType, dictType.getDictType()));
                    DictUtils.setDictCache(dictType.getDictType(), dictDatas);
                }
            }
        });
    }
}
